#include "AI.h"
AI::AI()
{
}

AI::~AI()
{
}

int AI::JudgeLiveOne(CBoard b, int judge_x, int judge_y, int direction, int color)
{
    int same[8] = {0}; //不同方向相邻连续相同颜色棋子数
                       /*向左搜索*/
    int i = judge_x, j = judge_y - 1;
    while (j >= 0 && b.board[i][j] == color)
    {
        j--;
        same[0]++;
    }

    /*左下搜索*/
    i = judge_x + 1, j = judge_y - 1;

    while (i < 15 && j >= 0 && b.board[i][j] == color)
    {
        i++;
        j--;
        same[1]++;
    }

    /*向下搜索*/
    i = judge_x + 1, j = judge_y;

    while (i < 15 && b.board[i][j] == color)
    {
        i++;
        same[2]++;
    }

    /*右下搜索*/
    i = judge_x + 1, j = judge_y + 1;

    while (i < 15 && j < 15 && b.board[i][j] == color)
    {
        i++;
        j++;
        same[3]++;
    }

    /*向右搜索*/
    i = judge_x, j = judge_y + 1;

    while (i < 15 && b.board[i][j] == color)
    {
        j++;
        same[4]++;
    }

    /*右上搜索*/
    i = judge_x - 1, j = judge_y + 1;

    while (i >= 0 && j < 15 && b.board[i][j] == color)
    {
        i--;
        j++;
        same[5]++;
    }

    /*向上搜索*/
    i = judge_x - 1, j = judge_y;

    while (i >= 0 && b.board[i][j] == color)
    {
        i--;
        same[6]++;
    }

    /*左上搜索*/
    i = judge_x - 1, j = judge_y - 1;

    while (i >= 0 && j >= 0 && b.board[i][j] == color)
    {
        i--;
        j--;
        same[7]++;
    }

    /*判断两端*/
    int key_x, key_y; //小于4一侧关键点坐标
    int key_m, key_n;
    same[direction]++; //相隔点数加一，用于计算关键点坐标
    same[direction + 4]++;
    /*计算关键点坐标*/
    switch (direction % 4)
    {
    case 0:
        key_x = judge_x;
        key_y = judge_y - same[direction];
        key_m = judge_x;
        key_n = judge_y + same[direction + 4];
        break;
    case 1:
        key_x = judge_x + same[direction];
        key_y = judge_y - same[direction];
        key_m = judge_x - same[direction + 4];
        key_n = judge_y + same[direction + 4];
        break;
    case 2:
        key_x = judge_x + same[direction];
        key_y = judge_y;
        key_m = judge_x - same[direction + 4];
        key_n = judge_y;
        break;
    default:
        key_x = judge_x + same[direction];
        key_y = judge_y + same[direction];
        key_m = judge_x - same[direction + 4];
        key_n = judge_y - same[direction + 4];
        break;
    }
    if (b.board[key_x][key_y] == 0 && b.board[key_m][key_n] == 0 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 5;
    }
    if (b.board[key_x][key_y] == 1 || b.board[key_m][key_n] == 1 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 3;
    }
    if (b.board[key_x][key_y] == 1 && b.board[key_m][key_n] == 1 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 1;
    }
    return 0;
}
int AI::JudgeLiveTwo(CBoard b, int judge_x, int judge_y, int direction, int color)
{
    int same[8] = {0}; //不同方向相邻连续相同颜色棋子数
                       /*向左搜索*/
    int i = judge_x, j = judge_y - 1;
    while (j >= 0 && b.board[i][j] == color)
    {
        j--;
        same[0]++;
    }

    /*左下搜索*/
    i = judge_x + 1, j = judge_y - 1;

    while (i < 15 && j >= 0 && b.board[i][j] == color)
    {
        i++;
        j--;
        same[1]++;
    }

    /*向下搜索*/
    i = judge_x + 1, j = judge_y;

    while (i < 15 && b.board[i][j] == color)
    {
        i++;
        same[2]++;
    }

    /*右下搜索*/
    i = judge_x + 1, j = judge_y + 1;

    while (i < 15 && j < 15 && b.board[i][j] == color)
    {
        i++;
        j++;
        same[3]++;
    }

    /*向右搜索*/
    i = judge_x, j = judge_y + 1;

    while (i < 15 && b.board[i][j] == color)
    {
        j++;
        same[4]++;
    }

    /*右上搜索*/
    i = judge_x - 1, j = judge_y + 1;

    while (i >= 0 && j < 15 && b.board[i][j] == color)
    {
        i--;
        j++;
        same[5]++;
    }

    /*向上搜索*/
    i = judge_x - 1, j = judge_y;

    while (i >= 0 && b.board[i][j] == color)
    {
        i--;
        same[6]++;
    }

    /*左上搜索*/
    i = judge_x - 1, j = judge_y - 1;

    while (i >= 0 && j >= 0 && b.board[i][j] == color)
    {
        i--;
        j--;
        same[7]++;
    }

    /*判断两端*/
    int key_x, key_y; //小于4一侧关键点坐标
    int key_m, key_n;
    same[direction]++; //相隔点数加一，用于计算关键点坐标
    same[direction + 4]++;
    /*计算关键点坐标*/
    switch (direction % 4)
    {
    case 0:
        key_x = judge_x;
        key_y = judge_y - same[direction];
        key_m = judge_x;
        key_n = judge_y + same[direction + 4];
        break;
    case 1:
        key_x = judge_x + same[direction];
        key_y = judge_y - same[direction];
        key_m = judge_x - same[direction + 4];
        key_n = judge_y + same[direction + 4];
        break;
    case 2:
        key_x = judge_x + same[direction];
        key_y = judge_y;
        key_m = judge_x - same[direction + 4];
        key_n = judge_y;
        break;
    default:
        key_x = judge_x + same[direction];
        key_y = judge_y + same[direction];
        key_m = judge_x - same[direction + 4];
        key_n = judge_y - same[direction + 4];
        break;
    }
    if (b.board[key_x][key_y] == 0 && b.board[key_m][key_n] == 0 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 5;
    }
    if (b.board[key_x][key_y] == 1 || b.board[key_m][key_n] == 1 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 3;
    }
    if (b.board[key_x][key_y] == 1 && b.board[key_m][key_n] == 1 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 1;
    }
    return 0;
}
int AI::JudgeLiveThree(CBoard b, int judge_x, int judge_y, int direction, int color)
{
    int same[8] = {0}; //不同方向相邻连续相同颜色棋子数
                       /*向左搜索*/
    int i = judge_x, j = judge_y - 1;
    while (j >= 0 && b.board[i][j] == color)
    {
        j--;
        same[0]++;
    }

    /*左下搜索*/
    i = judge_x + 1, j = judge_y - 1;

    while (i < 15 && j >= 0 && b.board[i][j] == color)
    {
        i++;
        j--;
        same[1]++;
    }

    /*向下搜索*/
    i = judge_x + 1, j = judge_y;

    while (i < 15 && b.board[i][j] == color)
    {
        i++;
        same[2]++;
    }

    /*右下搜索*/
    i = judge_x + 1, j = judge_y + 1;

    while (i < 15 && j < 15 && b.board[i][j] == color)
    {
        i++;
        j++;
        same[3]++;
    }

    /*向右搜索*/
    i = judge_x, j = judge_y + 1;

    while (i < 15 && b.board[i][j] == color)
    {
        j++;
        same[4]++;
    }

    /*右上搜索*/
    i = judge_x - 1, j = judge_y + 1;

    while (i >= 0 && j < 15 && b.board[i][j] == color)
    {
        i--;
        j++;
        same[5]++;
    }

    /*向上搜索*/
    i = judge_x - 1, j = judge_y;

    while (i >= 0 && b.board[i][j] == color)
    {
        i--;
        same[6]++;
    }

    /*左上搜索*/
    i = judge_x - 1, j = judge_y - 1;

    while (i >= 0 && j >= 0 && b.board[i][j] == color)
    {
        i--;
        j--;
        same[7]++;
    }

    /*判断三两端*/
    int key_x, key_y; //小于4一侧关键点坐标
    int key_m, key_n;
    same[direction]++; //相隔点数加一，用于计算关键点坐标
    same[direction + 4]++;
    /*计算关键点坐标*/
    switch (direction % 4)
    {
    case 0:
        key_x = judge_x;
        key_y = judge_y - same[direction];
        key_m = judge_x;
        key_n = judge_y + same[direction + 4];
        break;
    case 1:
        key_x = judge_x + same[direction];
        key_y = judge_y - same[direction];
        key_m = judge_x - same[direction + 4];
        key_n = judge_y + same[direction + 4];
        break;
    case 2:
        key_x = judge_x + same[direction];
        key_y = judge_y;
        key_m = judge_x - same[direction + 4];
        key_n = judge_y;
        break;
    default:
        key_x = judge_x + same[direction];
        key_y = judge_y + same[direction];
        key_m = judge_x - same[direction + 4];
        key_n = judge_y - same[direction + 4];
        break;
    }
    if (b.board[key_x][key_y] == 0 && b.board[key_m][key_n] == 0 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 5;
    }
    if (b.board[key_x][key_y] == 1 || b.board[key_m][key_n] == 1 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 3;
    }
    if (b.board[key_x][key_y] == 1 && b.board[key_m][key_n] == 1 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 1;
    }
    return 0;
}

int AI::JudgeLiveFour(CBoard b, int judge_x, int judge_y, int direction, int color)
{
    int same[8] = {0}; //不同方向相邻连续相同颜色棋子数
                       /*向左搜索*/
    int i = judge_x, j = judge_y - 1;
    while (j >= 0 && b.board[i][j] == color)
    {
        j--;
        same[0]++;
    }

    /*左下搜索*/
    i = judge_x + 1, j = judge_y - 1;

    while (i < 15 && j >= 0 && b.board[i][j] == color)
    {
        i++;
        j--;
        same[1]++;
    }

    /*向下搜索*/
    i = judge_x + 1, j = judge_y;

    while (i < 15 && b.board[i][j] == color)
    {
        i++;
        same[2]++;
    }

    /*右下搜索*/
    i = judge_x + 1, j = judge_y + 1;

    while (i < 15 && j < 15 && b.board[i][j] == color)
    {
        i++;
        j++;
        same[3]++;
    }

    /*向右搜索*/
    i = judge_x, j = judge_y + 1;

    while (i < 15 && b.board[i][j] == color)
    {
        j++;
        same[4]++;
    }

    /*右上搜索*/
    i = judge_x - 1, j = judge_y + 1;

    while (i >= 0 && j < 15 && b.board[i][j] == color)
    {
        i--;
        j++;
        same[5]++;
    }

    /*向上搜索*/
    i = judge_x - 1, j = judge_y;

    while (i >= 0 && b.board[i][j] == color)
    {
        i--;
        same[6]++;
    }

    /*左上搜索*/
    i = judge_x - 1, j = judge_y - 1;

    while (i >= 0 && j >= 0 && b.board[i][j] == color)
    {
        i--;
        j--;
        same[7]++;
    }

    /*判断活四*/
    int key_x, key_y; //小于4一侧关键点坐标
    int key_m, key_n;
    same[direction]++; //相隔点数加一，用于计算关键点坐标
    same[direction + 4]++;
    /*计算关键点坐标*/
    switch (direction % 4)
    {
    case 0:
        key_x = judge_x;
        key_y = judge_y - same[direction];
        key_m = judge_x;
        key_n = judge_y + same[direction + 4];
        break;
    case 1:
        key_x = judge_x + same[direction];
        key_y = judge_y - same[direction];
        key_m = judge_x - same[direction + 4];
        key_n = judge_y + same[direction + 4];
        break;
    case 2:
        key_x = judge_x + same[direction];
        key_y = judge_y;
        key_m = judge_x - same[direction + 4];
        key_n = judge_y;
        break;
    default:
        key_x = judge_x + same[direction];
        key_y = judge_y + same[direction];
        key_m = judge_x - same[direction + 4];
        key_n = judge_y - same[direction + 4];
        break;
    }
    if (b.board[key_x][key_y] == 0 && b.board[key_m][key_n] == 0 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 5;
    }
    if (b.board[key_x][key_y] == 1 || b.board[key_m][key_n] == 1 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 3;
    }
    if (b.board[key_x][key_y] == 1 && b.board[key_m][key_n] == 1 && key_m >= 0 && key_m < 15 && key_n >= 0 && key_n < 15 && key_x >= 0 && key_x < 15 && key_y >= 0 && key_y < 15)
    {
        return 1;
    }
    return 0;
}
int AI::Distribution(CBoard b)
{
    /*将棋盘每个子循环遍历，打分，相加得到总分*/
    int board_score = 0;
    int score_i = 0, score_j = 0; //定义循环变量
    while (score_i < 15)
    {
        score_j = 0;
        while (score_j < 15)
        {
            int same[8] = {0}; //不同方向相邻连续相同颜色棋子数
            /*向左搜索*/
            int i = score_i, j = score_j - 1;
            while (j >= 0 && b.board[i][j] == b.board[score_i][score_j])
            {
                j--;
                same[0]++;
            }
            /*左下搜索*/
            i = score_i + 1, j = score_j - 1;
            while (i < 15 && j >= 0 && b.board[i][j] == b.board[score_i][score_j])
            {
                i++;
                j--;
                same[1]++;
            }
            /*向下搜索*/
            i = score_i + 1, j = score_j;
            while (i < 15 && b.board[i][j] == b.board[score_i][score_j])
            {
                i++;
                same[2]++;
            }
            /*右下搜索*/
            i = score_i + 1, j = score_j + 1;
            while (i < 15 && j < 15 && b.board[i][j] == b.board[score_i][score_j])
            {
                i++;
                j++;
                same[3]++;
            }
            /*向右搜索*/
            i = score_i, j = score_j + 1;
            while (i < 15 && b.board[i][j] == b.board[score_i][score_j])
            {
                j++;
                same[4]++;
            }
            /*右上搜索*/
            i = score_i - 1, j = score_j + 1;
            while (i >= 0 && j < 15 && b.board[i][j] == b.board[score_i][score_j])
            {
                i--;
                j++;
                same[5]++;
            }
            /*向上搜索*/
            i = score_i - 1, j = score_j;
            while (i >= 0 && b.board[i][j] == b.board[score_i][score_j])
            {
                i--;
                same[6]++;
            }
            /*左上搜索*/
            i = score_i - 1, j = score_j - 1;
            while (i >= 0 && j >= 0 && b.board[i][j] == b.board[score_i][score_j])
            {
                i--;
                j--;
                same[7]++;
            }
            /*搜索完毕*/
            if (b.board[score_i][score_j] == -1) //对白子点进行打分
            {
                /*打分，单子10分，二子100分，三子1000分，活三3000分，冲四10000，活四50000，五子100000分，长连200000分*/
                int direction = 0; //方向变量
                while (direction < 4)
                {
                    if (same[direction] + same[direction + 4] >= 5) /*长连判断*/
                    {
                        board_score = board_score + 200000;
                    }
                    else if (same[direction] + same[direction + 4] == 4) //五子相连
                    {
                        board_score = board_score + 100000;
                    }
                    else if (same[direction] + same[direction + 4] == 3) //四子相连
                    {
                        board_score = board_score + JudgeLiveFour(b, score_i, score_j, direction, WHITE) * 10000;
                    }
                    else if (same[direction] + same[direction + 4] == 2) //三子相连
                    {
                        board_score = board_score + JudgeLiveThree(b, score_i, score_j, direction, WHITE) * 1000;
                    }
                    else if (same[direction] + same[direction + 4] == 1) //二子相连
                    {
                        board_score = board_score + JudgeLiveTwo(b, score_i, score_j, direction, WHITE) * 10;
                    }
                    else if (same[direction] + same[direction + 4] == 0) //单子
                    {
                        board_score = board_score + JudgeLiveOne(b, score_i, score_j, direction, WHITE);
                    }
                    direction++;
                }
            }
            if (b.board[score_i][score_j] == 1) //对黑棋点打分
            {
                /*打分，单子-10分，二子-100分，三子-1000分，活三-3000分，冲四-10000，活四-50000，五子-100000分，长连-200000分*/
                int direction = 0; //方向变量
                while (direction < 4)
                {
                    if (same[direction] + same[direction + 4] >= 5) /*长连判断*/
                    {
                        board_score = board_score - 200000;
                    }
                    else if (same[direction] + same[direction + 4] == 4) //五子相连
                    {
                        board_score = board_score - 100000;
                    }
                    else if (same[direction] + same[direction + 4] == 3) //四子相连
                    {
                        board_score = board_score - JudgeLiveFour(b, score_i, score_j, direction, BLACK) * 10000;
                    }
                    else if (same[direction] + same[direction + 4] == 2) //三子相连
                    {
                        board_score = board_score - JudgeLiveThree(b, score_i, score_j, direction, BLACK) * 1000;
                    }
                    else if (same[direction] + same[direction + 4] == 1) //二子相连
                    {
                        board_score = board_score - JudgeLiveTwo(b, score_i, score_j, direction, BLACK) * 10;
                    }
                    else if (same[direction] + same[direction + 4] == 0) //单子
                    {
                        board_score = board_score - JudgeLiveOne(b, score_i, score_j, direction, BLACK);
                    }
                    direction++;
                }
            }

            score_j++;
        }

        score_i++;
    }
    return board_score;
}

/*极大极小值回溯算法*/
int AI::MaxMin(CBoard b, int playertype, int deep)
{
    int bestvalue = 0; //得到最佳值，用来计算棋子位置
    int try_value = 0; //试探下子的值
    int max_value = 0;
    int min_value = 0;
    if (deep == 0)
    {
        return bestvalue = Distribution(b);
    }
    if (playertype == COMPUTER)
    {
        int search_i = 0, search_j = 0;
        while (search_i < 15)
        {
            search_j = 0;
            while (search_j < 15)
            {
                if (b.board[search_i][search_j] == 0)
                {
                    b.board[search_i][search_j] = playertype;
                    try_value = MaxMin(b, PLAYER1, deep - 1);
                    b.board[search_i][search_j] = 0;
                }
                if (try_value > max_value)
                {
                    max_value = try_value;
                }
                search_j++;
            }
            search_i++;
        }
        bestvalue = max_value;
    }
    if (playertype == PLAYER1)
    {
        int search_i = 0, search_j = 0;
        while (search_i < 15)
        {
            search_j = 0;
            while (search_j < 15)
            {
                if (b.board[search_i][search_j] == 0)
                {
                    b.board[search_i][search_j] = playertype;
                    try_value = MaxMin(b, COMPUTER, deep - 1);
                    b.board[search_i][search_j] = 0;
                }
                if (try_value < min_value)
                {
                    min_value = try_value;
                }
                search_j++;
            }
            search_i++;
        }
        bestvalue = min_value;
    }
    return bestvalue;
}

void AI::AISet(CBoard b)
{
    Piece AI_piece = Piece(); //创建AI的棋子链
    int target_value = 0;     //找目标值的点
    target_value = MaxMin(b, COMPUTER,1);
    int local_value = 0;
    int i = 0, j = 0; //循环变量
    while (i < 15)
    {
        j = 0;
        while (j < 15)
        {
            if (b.board[i][j] == 0)
            {
                b.board[i][j] = -1;
                local_value=Distribution(b);
                if (local_value == target_value)
                {
                    AI_piece.row = i;
                    AI_piece.column = j;
                    AIlist.push_front(AI_piece);
                }
                b.board[i][j] = 0;
            }
            j++;
        }
        i++;
    }
}

int AI::GetAIRow()
{
    int AI_row = AIlist.front().row;
    return AI_row;
}

int AI::GetAIColumn()
{
    int AI_column = AIlist.front().column;
    return AI_column;
}